package com.wangsan.study.security;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

import com.wangsan.study.domain.RoleEntity;
import com.wangsan.study.domain.UserEntity;
import com.wangsan.study.domain.UserEntityRepository;

/**
 * CustomUserDetailsService
 *
 * @author wangsan
 * @date 2016/12/8
 */
@Transactional
public class CustomUserDetailsService implements UserDetailsService {
	@Autowired
	private UserEntityRepository userEntityRepository;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		UserDetails userDetails = userMap().get(username);
		userDetails=null;

		// from db
		if (userDetails == null) {
			userDetails = fromDb(username);
		}

		return userDetails;
	}

	private Map<String, UserDetails> userMap() {
		Map<String, UserDetails> userDetailsMap = new HashMap<>();
		userDetailsMap.put("user", new User("user", "user", AuthorityUtils.createAuthorityList("ROLE_User")));
		userDetailsMap.put("test", new User("test", "test", AuthorityUtils.createAuthorityList("ROLE_Test")));
		userDetailsMap.put("admin", new User("admin", "admin", AuthorityUtils.createAuthorityList("ROLE_Admin")));

		return userDetailsMap;
	}

	private User fromDb(String username) {
		final UserEntity userEntity = userEntityRepository.findByUsername(username);
		if (userEntity == null || userEntity.getRoleEntitySet() == null) {
			return null;
		}

		final Set<RoleEntity> roleEntitySet = userEntity.getRoleEntitySet();
		final Set<SimpleGrantedAuthority> grantedAuthoritySet =
			roleEntitySet.stream().map(r -> new SimpleGrantedAuthority("ROLE_" + r.getName()))
				.collect(Collectors.toSet());

		return new User(userEntity.getUsername(), userEntity.getPassword(), grantedAuthoritySet);
	}
}
